package com.demo.service.riot;

import com.demo.config.RiotConfig;
import com.demo.entity.riot.RankEntry;
import com.demo.entity.riot.Summoner;
import com.demo.exception.ApiException;
import com.demo.mapper.riot.RankMapper;
import com.demo.service.riot.Async.RankDataAsyncService;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class RiotRankService {
    private final RiotBasicService riotBasicService;
    private final SummonerService summonerService;
    private final RankDataAsyncService rankDataAsyncService;
    private final RiotConfig riotConfig;

    private final String LEAGUE_ENTRIES_BY_PUUID = "/lol/league/v4/entries/by-puuid/{puuid}";

    @Resource
    private RankMapper rankMapper;

    public RiotRankService(RiotBasicService riotBasicService, SummonerService summonerService, RankDataAsyncService rankDataAsyncService, RiotConfig riotConfig) {
        this.riotBasicService = riotBasicService;
        this.summonerService = summonerService;
        this.rankDataAsyncService = rankDataAsyncService;
        this.riotConfig = riotConfig;
    }

    private List<RankEntry> getRankInfoByDB(String serverRegion, String puuid) {
        return rankMapper.getRankEntries(serverRegion, puuid);
    }

    private List<RankEntry> getRankInfoByApi(String serverRegion, String puuid) throws ApiException {
        Map<String, String> pathParams = new HashMap<>();
        pathParams.put("serverRegion", serverRegion);
        pathParams.put("puuid", puuid);
        JsonNode result = riotBasicService.getJsonByParams(riotConfig, pathParams, null, serverRegion, LEAGUE_ENTRIES_BY_PUUID, "排位", true);
        List<RankEntry> list = new ArrayList<>();
        for(JsonNode entry: result) {
            RankEntry rankEntry = new RankEntry(
                    entry.get("queueType").asText(),
                    entry.get("tier").asText(),
                    entry.get("rank").asText(),
                    entry.get("leaguePoints").asInt(),
                    entry.get("wins").asInt(),
                    entry.get("losses").asInt()
                    );
            list.add(rankEntry);
        }
        return list;
    }

    private void createRankEntries(String puuid, List<RankEntry> rankEntries) {
        rankMapper.insertRankEntries(puuid, rankEntries);
    }

    public List<RankEntry> getRankInfo(String serverRegion, String puuid) throws ApiException {
        if(rankMapper.hasRankEnty(serverRegion, puuid)) {
            if(shouldUpdateRankInfo(serverRegion, puuid)) {
                List<RankEntry> rankEntries = getRankInfoByApi(serverRegion, puuid);
                if(!rankEntries.isEmpty()) {
                    rankDataAsyncService.processRankDataAsync(serverRegion, puuid, rankEntries, "update");
                }
                return rankEntries;
            } else{
                return getRankInfoByDB(serverRegion, puuid);
            }
        } else {
            List<RankEntry> rankEntries = getRankInfoByApi(serverRegion, puuid);
            Summoner summoner = summonerService.getSummonerByPuuid(serverRegion, puuid);
            if(!rankEntries.isEmpty()){
                rankDataAsyncService.processRankDataAsync(serverRegion, puuid, rankEntries, "create");
            }
            return rankEntries;
        }
    }

    private void updateRankEntries(String serverRegion, String puuid, List<RankEntry> rankEntries) throws ApiException {
        Summoner summoner = summonerService.getSummonerByPuuid(serverRegion, puuid);
        for(RankEntry rankEntry: rankEntries) {
            rankMapper.updateRankEntries(serverRegion, summoner.getPuuid(), rankEntry);
        }
    }

    public void updateRankEntries(String serverRegion, String puuid) throws ApiException {
        Summoner summoner = summonerService.getSummonerByPuuid(serverRegion, puuid);
        List<RankEntry> rankEntries = getRankInfoByApi(serverRegion, puuid);
        updateRankEntries(serverRegion, puuid, rankEntries);
    }

    private Boolean shouldUpdateRankInfo(String serverRegion, String puuid) {
        LocalDateTime now = LocalDateTime.now();
        List<LocalDateTime> lastUpdate = rankMapper.getLastUpdate(serverRegion, puuid);
        for(LocalDateTime lastUpdateTime: lastUpdate) {
            Duration duration = Duration.between(lastUpdateTime, now);
            if(duration.toDays() > 3) return true;
        }
        return false;
    }

    public long getUpdateDuration(String serverRegion, String puuid) {
        LocalDateTime now = LocalDateTime.now();
        List<LocalDateTime> lastUpdate = rankMapper.getLastUpdate(serverRegion, puuid);
        long updateDuration = Long.MAX_VALUE;
        for(LocalDateTime lastUpdateTime: lastUpdate) {
            Duration duration = Duration.between(lastUpdateTime, now);
            if(duration.toHours() < updateDuration) updateDuration = duration.toHours();
        }
        return updateDuration;
    }
}
